<?php
/**
 * Created by PhpStorm.
 * User: zhangrxiang
 * Date: 17-2-23
 * Time: 下午7:53
 */


class Visibility{
    private $private = "private";
    protected $protected = 'protected';
    public $public = 'public';

    private $pri;

    private function privateFun(){
        echo $this->private.PHP_EOL;
        echo __METHOD__.PHP_EOL;
    }

    protected function protectedFun(){
        echo __METHOD__.PHP_EOL;
    }

    public function publicFun(){
        echo __METHOD__.PHP_EOL;
    }

    public function getPri(Visibility $vis){
        $this->getPriFun();
        return $this->pri = $vis;
    }

    public function getPriFun(){
        $this->privateFun();
    }
}


$visibility = new Visibility();
$visibility->publicFun();

$visibility->getPri(new Visibility())->getPriFun();




abstract class Father{

    private $pri = __CLASS__;

    public function getPri(){
        $this->pri();
    }
    public function getPro(){
        $this->pro();
    }

    private function pri(){
        echo $this->pri.PHP_EOL;
    }

    protected function pro(){
        $this->pri();
    }

}

class Son extends Father{

    private $pri = __CLASS__;

    private function pri(){
        echo $this->pri.PHP_EOL;
    }

    protected function pro(){
        $this->pri();
    }
}

$son = new Son();
$son->getPri(); //Father
$son->getPro(); //Son



// /etc/php/7.0/cli/php.ini
echo php_ini_loaded_file().PHP_EOL;
echo php_ini_scanned_files().PHP_EOL;
echo php_sapi_name().PHP_EOL;
//7.0.13-0ubuntu0.16.04.1
echo phpversion().PHP_EOL;

echo serialize(phpversion('swoole'));



class Sealed { private $value = 'foo'; }

$sealed = new Sealed;
var_dump($sealed); // private $value => string(3) "foo"

call_user_func(Closure::bind(
    function () use ($sealed) { $sealed->{'value'} = 'BAZ'; },
    null,
    $sealed
));

var_dump($sealed); // private $value => string(3) "BAZ"


class Test {
    private function foo() {
        echo "Foo" . PHP_EOL;
    }
    protected function bar() {
        echo "bar" . PHP_EOL;
    }

    static function foobar(Test $test) {
        $test->bar(); // works
        $test->foo(); // works
    }
}

function simple_function() {
    $test = new Test();

//    $test->bar(); // does not work

//    $test->foo(); // does not work

    Test::foobar($test); // works
}

simple_function();



//////////////////////////////////////////////////////////////////////////////
abstract class Dispatcher {
    protected function &accessProperty (self $pObj, $pName) {
        return $pObj->$pName;
    }
    protected function invokeMethod ($pObj, $pName, $pArgs) {
        return call_user_func_array(array($pObj, $pName), $pArgs);
    }
}

class Person extends Dispatcher {
    private $name;
    protected $phoneNumbers;

    public function __construct ($pName) {
        $this->name = $pName;
        $this->phoneNumbers = array();
    }
    public function addNumber (PhoneNumber $pNumber, $pLabel) {
        $this->phoneNumbers[$pLabel] = $pNumber;

        // this does not work, because "owner" is protected:
        // $pNumber->owner = $this;

        // instead, we get a reference from the dispatcher:
        $p =& $this->accessProperty($pNumber, "owner");

        // ... and change that:
        $p = $this;
    }
    public function call ($pLabel) {
        // this does not work since "call" is protected:
        // $this->phoneNumbers[$pLabel]->call();

        // instead, we dispatch the call request:
        $this->invokeMethod($this->phoneNumbers[$pLabel], "call", array());
    }
}

class PhoneNumber extends Dispatcher {
    private $countryCode;
    private $areaCode;
    private $number;
    protected $owner;

    public function __construct ($pCountryCode, $pAreaCode, $pNumber) {
        $this->countryCode = $pCountryCode;
        $this->areaCode = $pAreaCode;
        $this->number = $pNumber;
    }

    protected function call () {
        echo(" calling " . $this->countryCode . "-" . $this->areaCode . "-" . $this->number . "\n");
    }
}

$person = new Person("John Doe");
$number1 = new PhoneNumber(12, 345, 67890);
$number2 = new PhoneNumber(34, 5678, 90123);
$person->addNumber($number1, "home");
$person->addNumber($number2, "office");
$person->call("home");